package io.gitee.minelx.commontools.date;

import io.gitee.minelx.commontools.common.ComparableOperator;

import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.Objects;
import java.util.stream.IntStream;

public final class ClockValues implements Comparable<ClockValues> {
    private final int year;
    private final int month;
    private final int day;
    private final int hour;
    private final int minute;
    private final int second;
    private final int millisecond;
    private final List<Integer> values;

    ClockValues(int year, int month, int day, int hour, int minute, int second, int millisecond) {
        this.year = year;
        this.month = month;
        this.day = day;
        this.hour = hour;
        this.minute = minute;
        this.second = second;
        this.millisecond = millisecond;
        values = Arrays.asList(year, month, day, hour, minute, second, millisecond);
    }

    public ComparableOperator<ClockValues> op() {
        return new ComparableOperator<>(this);
    }

    @Override
    public int compareTo(ClockValues another) {
        return IntStream.of(year - another.year,
                        month - another.month,
                        day - another.day,
                        hour - another.hour,
                        minute - another.minute,
                        second - another.second,
                        millisecond - another.millisecond)
                .filter(which -> which != 0)
                .findFirst().orElse(0);
    }

    public int[] range(int far) {
        return values.subList(0, far).stream().mapToInt(unboxedHere -> unboxedHere).toArray();
    }

    public int year() {
        return year;
    }

    public int month() {
        return month;
    }

    public int day() {
        return day;
    }

    public int hour() {
        return hour;
    }

    public int minute() {
        return minute;
    }

    public int second() {
        return second;
    }

    public int millisecond() {
        return millisecond;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) return true;
        if (obj == null || obj.getClass() != this.getClass()) return false;
        ClockValues that = (ClockValues) obj;
        return this.year == that.year &&
                this.month == that.month &&
                this.day == that.day &&
                this.hour == that.hour &&
                this.minute == that.minute &&
                this.second == that.second &&
                this.millisecond == that.millisecond;
    }

    @Override
    public int hashCode() {
        return Objects.hash(year, month, day, hour, minute, second, millisecond);
    }

    @Override
    public String toString() {
        return "ClockValues{" +
                "year=" + year + ", " +
                "month=" + month + ", " +
                "day=" + day + ", " +
                "hour=" + hour + ", " +
                "minute=" + minute + ", " +
                "second=" + second + ", " +
                "millisecond=" + millisecond + '}';
    }

    static ClockValues fromCalendar(Calendar self) {
        return new ClockValues(self.get(Calendar.YEAR),
                self.get(Calendar.MONTH) + 1,
                self.get(Calendar.DAY_OF_MONTH),
                self.get(Calendar.HOUR_OF_DAY),
                self.get(Calendar.MINUTE),
                self.get(Calendar.SECOND),
                self.get(Calendar.MILLISECOND));
    }
}
